﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.Data;
using System.Windows;


//COM references
//using STATCONNECTORCLNTLib;
using StatConnectorCommonLib;
using Interop.STATCONNECTORSRVLib;
using System.IO;

namespace proyecto
{
    class R_Application
    {

        StatConnectorClass RConnector;

        public R_Application()
        {
            
                RConnector = new StatConnectorClass();
                RConnector.Init("R");
            
            
        }

        public void OpenConnection()
        {
            
                RConnector.Close();
                RConnector = new StatConnectorClass();
                RConnector.Init("R");
            
        }

        public void CloseConnection()
        {
            RConnector.Close();
        }

        public bool DatatableToFile(DataTable table, string FileName, bool transpose)
        {

            /*try
            {*/
            //MessageBox.Show("enter");
            //MessageBox.Show(FileName);
                StreamWriter writer = new StreamWriter(FileName);

                if (transpose)

                    for (int i = 0; i < table.Columns.Count; i++)
                    {

                        writer.Write(table.Columns[i].Caption + "\t");
                        for (int j = 0; j < table.Rows.Count; j++)
                        {
                            writer.Write(table.Rows[j][i].ToString());
                            if (j + 1 != table.Columns.Count)
                                writer.Write("\t");
                            else
                                writer.Write("\n");
                        }

                    }

                else
                {
                    //MessageBox.Show("no transponer");
                    for (int i = 0; i < table.Columns.Count; i++)
                    {
                        //writer.Write(table.Columns[i].Caption);
                        if (i + 1 != table.Columns.Count)
                            writer.Write(table.Columns[i].Caption+"\t");
                        else
                        {
                            //MessageBox.Show("fin de línea");
                            writer.Write(table.Columns[i].Caption+"\r\n");
                        }
                    }

                    for (int i = 0; i < table.Rows.Count; i++)
                        for (int j = 0; j < table.Columns.Count; j++)
                        {
                            writer.Write(table.Rows[i][j].ToString());
                            if (j + 1 != table.Columns.Count)
                                writer.Write("\t");
                            else
                                writer.Write("\r\n");
                        }
                }

                writer.Close();
            /*}

            catch (Exception e)
            {

                MessageBox.Show("Error while writing file");

                return false;
            }*/

            return true;

        }


        public bool FileToDatatable(ref DataTable table, string FileName, bool transpose)
        {
            /*try
            {*/
                

                StreamReader reader = new StreamReader(FileName);

                string FullFile = reader.ReadToEnd();
                FullFile.Trim();

                string[] FileRows = FullFile.Trim().Split('\n');

                string[][] FileCells = new string[FileRows.Length][];

                for (int i = 0; i < FileRows.Length; i++)
                {

                    FileCells[i] = FileRows[i].Trim().Split('\t', ' ');
                }

                /*string name = FileName;

                int lastChar = 0;

                for (int i = 0; i < name.Length; i++)
                    if (name[i] == '\\')
                        lastChar = i;

                name = name.Remove(0, lastChar + 1);

                name = name.Replace(".txt", "");

                table = new DataTable(name);*/

                if (transpose)
                {

                    for (int i = 0; i < FileRows.Length; i++)
                    {
                        DataColumn column = new DataColumn(FileCells[i][0], typeof(string));
                        table.Columns.Add(column);
                    }

                    for (int i = 1; i < FileCells[0].Length; i++)
                    {
                        DataRow row = table.NewRow();
                        for (int j = 0; j < FileRows.Length; j++)
                        {
                            row[j] = FileCells[j][i];
                        }

                        table.Rows.Add(row);

                    }
                }


                else
                {

                    for (int i = 0; i < FileCells[0].Length; i++)
                    {
                        DataColumn column = new DataColumn(FileCells[0][i], typeof(string));
                        table.Columns.Add(column);
                    }

                    for (int i = 1; i < FileRows.Length; i++)
                    {
                        DataRow row = table.NewRow();
                        for (int j = 0; j < FileCells[0].Length; j++)
                        {
                            row[j] = FileCells[i][j];
                        }

                        table.Rows.Add(row);

                    }

                }

            

            /*}

            catch (Exception e)
            {

                MessageBox.Show("Error while loading file");

                return false;
            }*/

                reader.Close();

            return true;

                

        }


        private bool detectARGS(ref string[] args, string RFile, ref int TableIndex, ref bool transpose){
            int index = RFile.IndexOf("ARGS[1]");
            int argCount=0;
            //MessageBox.Show(RFile);
            

            if (index==-1){

                //MessageBox.Show("Saliendo");
                args = new string[1];
                return true;
            }

            argCount++;

            for (; index!=-1; argCount++){
                index = RFile.IndexOf("ARGS["+(argCount+1).ToString()+"]");
            }

            argCount--;

            args = new string[argCount];

            for (int i = 0; i<argCount; i++)
                args[i] = "ARGS["+i.ToString()+"]";


            SelectARGS select = new SelectARGS(args, argCount);

            select.ShowDialog();

            if (!select.getOK())
                return false;

            transpose = select.getTranspose();

            string argsValues = "";
            string current = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );
            current = current.Replace("file:\\", "");
            
            //MessageBox.Show(current);
            for (int i = 0; i<argCount; i++){

                switch (select.getArgType(i)){

                    case 0:

                        int index_ = select.getTableValue(i);

                        //MessageBox.Show("Table "+index_.ToString());
                        
                        DatatableToFile(Window1.dat[0].getTable(index_), current+"\\temp\\RInputMatrix"+i.ToString()+".txt", transpose);

                        if (i==0)
                        {
                            
                            TableIndex = index_;
                            argsValues = argsValues+"\""+current.Replace("\\", "\\\\")+"\\\\temp\\\\RInputMatrix"+i.ToString()+".txt\"";
                            //MessageBox.Show(current.Replace("\\", "\\\\") + "\\\\temp\\\\RInputMatrix" + i.ToString());
                        }
                        else
                            argsValues = argsValues+", "+"\""+current.Replace("\\", "\\\\")+"\\\\temp\\\\RInputMatrix"+i.ToString()+".txt\"";

                        break;

                    case 1:

                        argsValues = argsValues+", \""+current.Replace("\\", "\\\\")+"\\\\temp\\\\ROutputMatrix.txt\"";

                        break;

                    case 2:

                        argsValues = argsValues+", "+select.getIntValue(i).ToString();

                        break;

                    case 3:

                        argsValues = argsValues+", "+select.getDoubleValue(i).ToString();

                        break;

                    case 4:

                        argsValues = argsValues+", \""+select.getStringValue(i)+"\"";

                        break;

                    default:

                        return false;

                


                }

            }
            //MessageBox.Show(argsValues);
            RConnector.Evaluate("ARGS<-c("+argsValues+")");

            object o = RConnector.GetSymbol("ARGS");
            string[] random = (string[])o;
            /*foreach (string d in random)
            {
                MessageBox.Show(d);
            }*/

            return true;

        }
            


        public bool Transformate(string RFile)
        {

            StreamReader reader = new StreamReader(RFile);

            string File = reader.ReadToEnd().Trim().Replace("\n\n", "\n").Replace("args","ARGS");

            string[] Sentences = File.Split('\n');

            for (int i = 0; i < Sentences.Length; i++)
                Sentences[i].Trim();

            string [] args = new string[0];

            bool Transpose = false;

            int TableIndex = 0;

            if (!detectARGS(ref args, File, ref TableIndex, ref Transpose))
                return false;

            try
            {
                for (int i = 0; i < Sentences.Length; i++)
                {
                    //MessageBox.Show(Sentences[i].Replace("\r", ""));
                    RConnector.Evaluate(Sentences[i].Replace("\r", ""));
                }
            }
            catch (Exception e)
            {
                /*MessageBox.Show("Invalid R file");
                return false;*/
            }


            DataTable AuxTable = new DataTable(Path.GetFileNameWithoutExtension(RFile).Replace(Path.GetDirectoryName(RFile), "").Replace("\\", ""));

            FileToDatatable(ref AuxTable, System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", "")+"\\temp\\ROutputMatrix.txt", Transpose);

            if (AuxTable.Columns.Count != Window1.dat[0].getTable(TableIndex).Columns.Count || AuxTable.Rows.Count != Window1.dat[0].getTable(TableIndex).Rows.Count)
            {

                MessageBox.Show("Invalid operation. Not a valid transformate operation");
                return false;
            }



            //DataColumn column = Window1.dat[0].getTable(TableIndex).Columns.Add(Path.GetFileNameWithoutExtension(RFile).Replace(Path.GetDirectoryName(RFile), "").Replace("\\", ""), AuxTable.Columns[0].GetType());


            DataTable OutputTable = (Window1.dat[0].getTable(TableIndex)).Clone();

            for (int j = 0; j < AuxTable.Rows.Count; j++)
            {
                DataRow row = OutputTable.NewRow();
                for (int k = 0; k < AuxTable.Columns.Count; k++)
                    switch (OutputTable.Columns[k].DataType.Name)
                    {

                        case "String":
                            row[k] = AuxTable.Rows[j][k];
                            break;
                        case "Int":
                            row[k] = Convert.ToInt32(AuxTable.Rows[j][k]);
                            break;
                        case "Double":
                            row[k] = Convert.ToDouble(AuxTable.Rows[j][k]);
                            break;
                        case "Bool":
                            row[k] = Convert.ToBoolean(AuxTable.Rows[j][k]);
                            break;

                    }
                OutputTable.Rows.Add(row);
            }


            reader.Close();

            OutputTable.TableName = AuxTable.TableName;

            Window1.dat[0].createTable(OutputTable);

            

            return true;



        }


        public bool calculate(string RFile)
        {

            StreamReader reader = new StreamReader(RFile);

            string File = reader.ReadToEnd().Trim().Replace("\n\n", "\n").Replace("args", "ARGS");

            string[] Sentences = File.Split('\n');

            for (int i = 0; i < Sentences.Length; i++)
                Sentences[i].Trim();

            string[] args = new string[0];

            bool Transpose = false;

            int TableIndex = 0;

            if (!detectARGS(ref args, File, ref TableIndex, ref Transpose))
                return false;

            try
            {
                for (int i = 0; i < Sentences.Length; i++)
                {
                    //MessageBox.Show(Sentences[i].Replace("\r", ""));
                    RConnector.Evaluate(Sentences[i].Replace("\r", ""));
                }
            }
            catch (Exception e)
            {
                /*MessageBox.Show("Invalid R file");
                return false;*/
            }

            DataTable AuxTable;
            DataColumn column;
            try
            {
                AuxTable = new DataTable(Path.GetFileNameWithoutExtension(RFile).Replace(Path.GetDirectoryName(RFile), "").Replace("\\", ""));

                FileToDatatable(ref AuxTable, System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", "") + "\\temp\\ROutputMatrix.txt", Transpose);

                if (AuxTable.Columns.Count != 1 || AuxTable.Rows.Count != Window1.dat[0].getTable(TableIndex).Rows.Count)
                {

                    MessageBox.Show("Invalid operation. Not a valid calculate operation");
                    return false;
                }



                column = Window1.dat[0].getTable(TableIndex).Columns.Add(Path.GetFileNameWithoutExtension(RFile).Replace(Path.GetDirectoryName(RFile), "").Replace("\\", ""), AuxTable.Columns[0].DataType);

                Window1.dat[0].getTable(TableIndex).Columns[Window1.dat[0].getTable(TableIndex).Columns.Count - 1].Caption = AuxTable.TableName;

                for (int i = 0; i < Window1.dat[0].getTable(TableIndex).Rows.Count; i++)
                    Window1.dat[0].getTable(TableIndex).Rows[i][Window1.dat[0].getTable(TableIndex).Columns.Count - 1] = AuxTable.Rows[i][0];

            }

            catch
            {
                MessageBox.Show("Error while adding new column");
                return false;
            }


            string current = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );
            current = current.Replace("file:\\", "");
            current = current+"\\temp\\RInputMatrix0.txt";

            for (int i = 0; i<20; i++)

                if (i != TableIndex && i != 2 && Window1.dat[0].isCreated(i))
                {

                    //MessageBox.Show(i.ToString());

                    try
                    {
                        System.IO.File.Delete(current);
                        System.IO.File.Delete(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", "") + "\\temp\\ROutputMatrix.txt");
                    }
                    catch
                    {
                        ;
                    }

                    if (!DatatableToFile(Window1.dat[0].getTable(i), current, Transpose))

                        return false;



                    try
                    {
                        for (int l = 0; l < Sentences.Length; l++)
                        {
                            //MessageBox.Show(Sentences[i].Replace("\r", ""));
                            RConnector.Evaluate(Sentences[l].Replace("\r", ""));
                        }
                    }
                    catch (Exception e)
                    {
                        /*MessageBox.Show("Invalid R file");
                        return false;*/
                    }


                    try
                    {
                        AuxTable = new DataTable(Path.GetFileNameWithoutExtension(RFile).Replace(Path.GetDirectoryName(RFile), "").Replace("\\", ""));



                        FileToDatatable(ref AuxTable, System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", "") + "\\temp\\ROutputMatrix.txt", Transpose);

                        if (AuxTable.Columns.Count != 1 || AuxTable.Rows.Count != Window1.dat[0].getTable(TableIndex).Rows.Count)
                        {

                            MessageBox.Show("Invalid operation. Not a valid calculate operation");
                            return false;
                        }

                        column = new DataColumn();

                        column = Window1.dat[0].getTable(i).Columns.Add(Path.GetFileNameWithoutExtension(RFile).Replace(Path.GetDirectoryName(RFile), "").Replace("\\", ""), AuxTable.Columns[0].DataType);

                        Window1.dat[0].getTable(i).Columns[Window1.dat[0].getTable(i).Columns.Count - 1].Caption = AuxTable.TableName;

                        for (int l = 0; l < Window1.dat[0].getTable(i).Rows.Count; l++)
                            Window1.dat[0].getTable(i).Rows[l][Window1.dat[0].getTable(i).Columns.Count - 1] = AuxTable.Rows[l][0];

                    }

                    catch
                    {
                        MessageBox.Show("Error while adding new column");
                        return false;
                    }
                }


            reader.Close();

            try
            {
                Window1.dat[0].increaseCols();
            }
            catch
            {
                MessageBox.Show("R_Application failed while adding new filters to data");
                return false;
            }

            

            return true;

        }

        public string clustering(DataTable table)
        {
            string current = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
            
            current = current.Replace("file:\\", "");
            
            DatatableToFile(table, current + "\\temp\\RInputMatrix.txt", false);
            
            string args = "";
            //args = args + "\"" + current.Replace("\\", "\\\\") + "\\\\temp\\\\RInputMatrix0.txt\"" + "," + "\"" + current.Replace("\\", "\\\\") + "\\\\temp\\\\Cluster" + table.ToString() + ".png\"";
            args = args + "\"" + current.Replace("\\", "\\\\") + "\\\\temp\\\\RInputMatrix" + ".txt\"";
            args = args + ", \"" + current.Replace("\\", "\\\\") + "\\\\temp\\\\Cluster"+table.ToString()+".wmf\"";
            //MessageBox.Show(args);
            RConnector.Evaluate("ARGS<-c("+args+")");
            //RConnector.Evaluate("\"ARGS[1]<-" + current.Replace("\\","\\\\") + "\\\\temp\\\\RInputMatrix0.txt\"");
            //RConnector.Evaluate("\"ARGS[2]<-" + current.Replace("\\","\\\\") + "\\\\temp\\\\Cluster" + table.ToString() + ".png\"");

            string RFile = current + "\\..\\..\\Resources\\Clustering.txt";

            StreamReader reader = new StreamReader(RFile);

            string[] r_commands = reader.ReadToEnd().Replace("\n\r", "\n").Replace("\r\n", "\n").Trim().Split('\n', '\r');
            for (int i = 0; i < r_commands.Length; i++)
                if (r_commands[i].Length > 2)
                {
                    //MessageBox.Show(r_commands[i]);
                    RConnector.EvaluateNoReturn(r_commands[i].Replace("\r", ""));
                }
            
            //RConnector.EvaluateNoReturn("source('c:\\\\Users\\\\DIRECTOR\\\\Desktop\\\\proyecto\\\\repositorio\\\\Clustering.r')");
            return (current + "\\temp\\Cluster" + table.ToString() + ".wmf");
        }
    }
}
